/**
 * @file:   edid_file.c
 * @note:   2013-2023,   < git.sochina.net/think3r >
 * @brief   EDID 文件读写相关操作.
            1. 从 *.bin / *.h 中读取 EDID数据
            2. 将 EDID 数据写入到 *.bin / *.h 中
 * @author: think3r
 * @date    2018/1/6
 * @note:
 * @note \n History:
   1.日    期: 2018/1/6
     作    者: think3r
     修改历史: 创建文件
 */
 
/*----------------------------------------------*/
/*                 头文件包含                   */
/*----------------------------------------------*/

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>

#include "../inc/common.h"
#include "../inc/edid.h"

/*----------------------------------------------*/
/*                 宏类型定义                   */
/*----------------------------------------------*/

#define __DEBUG__  

#ifdef __DEBUG__  
    #define DEBUG(format,...) printf("*["__FILE__ "  %s L:%04d]>   "format"",__FUNCTION__, __LINE__, ##__VA_ARGS__)  
#else  
    #define DEBUG(format,...)  
#endif


/*----------------------------------------------*/
/*                结构体定义                    */
/*----------------------------------------------*/

/*----------------------------------------------*/
/*                 函数声明                     */
/*----------------------------------------------*/

/*----------------------------------------------*/
/*                 全局变量                     */
/*----------------------------------------------*/
static const char edid_data_name[]= "EDID_data";



/*----------------------------------------------*/
/*                 函数定义                     */
/*----------------------------------------------*/


/**
 * @function:   GetFileSize
 * @brief:      获取  文件大小
 * @param[in]:  char * file_path   
 * @param[out]: UINT * file_size  
 * @param[out]: None
 * @return:     ERR
 */
ERR GetFileSize(char * file_path, UINT * file_size)  
{     
    FILE *infile = NULL;  
    ERR err = OK;
    
    if((infile=fopen(file_path,"rb"))==NULL)  
    {  
        printf( "\nCan not open the path: [%s] \n", file_path); 
        
        err = FILE_NOT_EXIT;
        return err;
    }  

    if(NULL == file_size)
    {
       err = PARAM_INVALID;
       return err;
    }
    
    *file_size = 0;
    fseek(infile, 0, SEEK_END);      /*移动到文件末尾*/  
    *file_size = ftell(infile);      /*定位文件位置指针的位置*/
    fclose(infile);    
    
    DEBUG("\tfile_Siez:[%u]\n", *file_size);        

#if 0    
    if( *file_size > 256)
    {
        printf("\t edid file is too big. file_Siez:[%ud]\n", *file_size);  

        err = EDID_FILE_TOO_BIG;
        return err;
    }
#endif

    return OK;  
} 


/**
 * read_bin
 * @brief      读取指定文件,指定大小的 EDID 数据到 buf 中.
 * @param[in]  UCHAR *path    
 * @param[in]  UCHAR *outbuf            
 * @param[in]  UINT size
 * @param[out] void
 * @return     void
 */
ERR read_bin(char *path, UCHAR *outbuf, UINT size)  
{  
    FILE *infile = NULL;  
    ERR err = OK;
    
    if((infile=fopen(path,"rb"))==NULL)  
    {  
        printf( "\nCan not open the path: %s \n", path); 
        
        err = FILE_NOT_EXIT;
        return err;
    }  

    if(size > 256)
    {
        size = 256;
        printf("[%s %d] err size:[%d]\n",__FUNCTION__, __LINE__, size);
    }
    fread(outbuf, sizeof(UCHAR), size, infile);    
    fclose(infile);  

    return err;
}


/**
 * @function:   readEDIDFrom_H_file
 * @brief:      从C语言头文件中读取EDID数据
 * @param[in]:  char  *inpath      
 * @param[out]: UINT8 *outbuf     
 * @param[in]:  UINT  inFileSize     
 * @param[in]:  UINT  read_number  读取到 outbuf 中的数据个数.
 * @return:     ERR
 */
ERR readEDIDFrom_H_file(char *inpath, UINT8 *outbuf, UINT inFileSize, UINT read_number)
{
    FILE *infile = NULL; 
    UINT i = 0, j = 0, idxNumber = 0, number = 0;  
    char * local_buf = NULL, * nextNumber = NULL;      
    char *inFileBuf = NULL;
    ERR err = OK;

    if(inFileSize > 1024*1024*100)
    {
        err = EDID_FILE_TOO_BIG;
        return err;
    }

    if(NULL == outbuf || 0 == read_number || read_number >= inFileSize)
    {   
       DEBUG("PARAM_INVALID\n");
       err = PARAM_INVALID;
       return err;
    }

    if((infile=fopen(inpath,"rb"))==NULL)  
    {  
       printf( "\nCan not open the path: %s \n", inpath); 
       
       err = FILE_NOT_EXIT;
       return err;
    }  
    
    inFileBuf = (char *) malloc (sizeof(char) * (inFileSize)); 
    if(inFileBuf == NULL)
    {
        err = MALLOC_ERR;
        fclose(infile); 
        return err;
    }
    
    fread(inFileBuf, sizeof(char), inFileSize, infile);    

    local_buf = strstr(inFileBuf, edid_data_name);

    if(local_buf == NULL)
    {
        err = EDID_DATA_NOT_FIND;     
        free(inFileBuf);
        fclose(infile);    
        return err;
    }

    local_buf = strstr(local_buf, "{");
    
    if( NULL == local_buf)
    {
        err = EDID_H_FILE_ARRY_ERR;
        free(inFileBuf);
        fclose(infile);  
        return err;
    }       
    else if(*local_buf == '{')
    {        
//        DEBUG("nexNumber    %c\n", local_buf[0]);
        local_buf++;
        idxNumber = local_buf - inFileBuf; /*计算当前数组在整个文件buf中的偏移*/        
    }
    
    nextNumber = local_buf;     /*已找到特定名称的数组, 开始进行数据的提取转换.*/
  
        
    j = 0;
    for( i = 0; i < inFileSize - idxNumber; i++ )
    {    
         if(isspace(*nextNumber) || *nextNumber == ',' )  /*空白字符或者分隔符*/
         {                                   
            nextNumber++;            
//            DEBUG("nexNumber    %c\n", nextNumber[0]);
         }
         else if(*nextNumber == '/')    /*处理头文件中的注释*/
         {
            nextNumber++;            
            
            if( (*(nextNumber)) == '*') //  /**/ 包含类注释 
            {    
                nextNumber++; 
                nextNumber = strstr(nextNumber, "*/");
                if( NULL == nextNumber)
                {
                    err = EDID_H_FILE_ARRY_ERR;
                    break;
                }                               
                nextNumber++;                
                nextNumber++;
            }
            else if ((*(nextNumber)) == '/')    /*   //类注释 */
            {
                while( *nextNumber != '\n')
                {
                    nextNumber++;
                }
                
                nextNumber++;
                
                if( *nextNumber == '\r')
                {
                    nextNumber++;
                }                
            }            
            else/*头文件格式错误*/
            {
                err = EDID_H_FILE_ARRY_ERR;
                break;
            }
         }
         else if((*(nextNumber)) == '}')     /*  数组结束 */
         {
            err = EDID_H_FILE_ARRY_END;
            break;
         }
         else
         {  
             /* 字符串数字 -> 数字; 第三个参数为0,根据前缀自动转换. */
             number = strtol(nextNumber ,&nextNumber , 0); 
            
             if( number < 0x100)
             {
                outbuf[j] = number;
             }
             else
             {
                 outbuf[j] = 0xaa;
             }
//             printf(" j:[%d],  0x%02x  \n", j , number);             
             number = 0;
             j ++;
             
             if(j >= read_number)
             {
                break;
             }
         }
    }

    free(inFileBuf);
    fclose(infile);    
    
    return err;
}


/**
 * @function:   writeEDIDdata2_H_file
 * @brief:      将EDID数据转化为C语言头文件形式的数组
 * @param[in]:  char *outpath  
 * @param[in]:  UINT8 *buf     
 * @param[in]:  UINT size      
 * @param[in]:  UINT warp_num  
 * @param[in]:  BOOL bSplit    
 * @param[out]: None
 * @return:     ERR
 */
ERR writeEDIDdata2_H_file(char *outpath, UINT8 *buf, UINT size, UINT warp_num, BOOL bSplit)  
{  
    FILE *infile = NULL; 
    UINT i = 0, k = 0, tmp = 0;  
    char local_buf[32]={0};      
    char local_buf2[256]={0}; 
    ERR err = OK;

    const char * const Au    = "/* \n *  @think3r , < git.oschina,net/think3r > \n*/ \n\n";
    const char * const Ifdef = "#ifndef   EDID_DATA__\n";
    const char * const Define ="#define   EDID_DATA__\n";
//    const char * const array = "\nstatic const unsigned char EDID[256] = {\n";    
    sprintf(local_buf2, "\nstatic const unsigned char %s[%d] = {\n",edid_data_name, size );  
    const char * const EndIF = "\n\n#endif //EDID_DATA__ \n";

    if((infile = fopen(outpath, "wa+")) == NULL)  
    {  
        printf("\n Can not open the path: [%s] \n", outpath);  

        err = FILE_NOT_EXIT;
        return err;
    }  
        
    fwrite(Au, strlen(Au), 1, infile);
    fwrite(Ifdef, strlen(Ifdef), 1, infile);
    fwrite(Define, strlen(Define), 1, infile);
//    fwrite(array, strlen(array), 1, infile);      
    fwrite(local_buf2, strlen(local_buf2), 1, infile);  
    
    for(i = 0; i < size; i++)  
    {  
        if(0 == i)
        {            
            fwrite("\t", strlen("\t"), 1, infile);     
        }
        
        k++;  
	    sprintf(local_buf, "0x%02x", buf[i]);  
        fwrite(local_buf, strlen(local_buf), 1, infile);  
        
        if(k != warp_num)  
        {
           fwrite(", ", strlen(", "), 1, infile);      
        }
        else  
        {
           fwrite(",", strlen(","), 1, infile);     
        }
        if((TRUE == bSplit) && (i == (size/2 - 1)) )      
        {
            DEBUG("i=[%d]\n",i);
            for(tmp = 0;  tmp < warp_num; tmp ++)
            {   
                if((tmp + i + 1) % warp_num == 0)
                {
                    sprintf(local_buf2, "\n\n\t/********************* 后 %d 字节 ***********************/\n\n\t", 
                            (size/2 + size%2 ));  
                    fwrite(local_buf2, strlen(local_buf2), 1, infile);
                }
                DEBUG("tmp=[%d]\n",tmp);
                sprintf(local_buf2, "      ");              
                fwrite(local_buf2, strlen(local_buf2), 1, infile);      
                
            }
        }
        if(k==warp_num)  
        {  
            k=0;  
            fwrite("\n\t", strlen("\n\t"), 1, infile);  
        }          
    }  

        fseek(infile, 0, SEEK_END);  
    
    if(k == 0)
    {
        fwrite("};", strlen("};"), 1, infile);  
    }
    else  
    {
        fwrite("\n};", strlen("\n};"), 1, infile);         
    }
   
    fwrite(EndIF, strlen(EndIF), 1, infile);  

    fclose(infile);  

    return ok;
}   

/**
 * @function:   writeEDIDdata2_bin_Files
 * @brief:      将 EDID 数据写到 bin 文件
 * @param[in]:  char *outFilePath   
 * @param[in]:  UCHAR * edid_data   
 * @param[in]:  UINT edid_data_len  
 * @param[out]: None
 * @return:     ERR
 */
ERR writeEDIDdata2_bin_Files(char *outFilePath, UCHAR * edid_data,  UINT edid_data_len)
{
    unsigned int write_number = 0;    
    FILE *infile = NULL;     
    ERR err = OK;
    
//    sprintf(outFileName,"%s_%d.bin", outFileName, edid_data_len);
    
	infile = fopen(outFilePath, "wb+");    
    if( NULL == infile )
    {
        printf(" open file %s Faild!!!!\n", *outFilePath);
        
        err = FILE_NOT_EXIT;        
        return err;
    }    

    write_number = fwrite(edid_data, 1, edid_data_len, infile);    
    if( write_number != edid_data_len)
    {        
        printf("\t edid_data_len:[%d], edid_data_write_len:[%d]\n", edid_data_len, write_number);        
        
        fclose(infile);  
        err = FAILD;
    }

    fclose(infile);
    
    return 0;
}




